import java.io.Serializable;
import java.util.ArrayList;
import java.util.GregorianCalendar;
/**
* DataSource stellt eine Liste dar in der saemtliche Messwerte aus
* allen Messstationen gespeichert werden.
* Die verschiedenen Messwerte werden beim Hinzutuegen auf Gueltigkeit ueberprueft
* Regelmaessige Backups koennen realisiert werden, indem man das backupIntervall setzt.
* Die Backups finden dann nach n gaddeten Messungen statt. n entspricht dem Backupintervall.
*
* @author Thomas Guerth 0725326
*
*/
public class DataSource implements Serializable {
private static final long serialVersionUID = 8554262013060381750L;
private ArrayList <Measuring> measurings = new ArrayList<Measuring>();
private Application app;
private int addcounter;
private int backupIntervall;
private int backupCounter;
private String backupSaveName;
/**
* Konstruktor
* @param app Applicationobjekt
*/
public DataSource(Application app){
this.app=app;
}
/**
* Fuegt Messwerte in die measuringsarraylist hinzu, falls diese korret sind
* @param measuring Messwert der hinzugefuegt werden soll
* @param password Passwort der Messstation die hinzugefuegt werden soll
* @return null wenn alles korrekt. Ansonsten String mit Warnung
* @throws ApplicationException
*/
public String add(Measuring measuring, String password)
throws ApplicationException{
String retArg = "";
//Passwort testen
if(!measuring.getPoint().equalsPassword(password)){
throw new ApplicationException("Wrong Password");
}
// Pruefung ob wert valide
if(this.isValid(measuring)!=null){
throw new ApplicationException(isValid(measuring));
}
// Bestimme den letzten Wert der auf dieser
//Messstation gemessen wurde
Measuring lastPointMeasuring =
getlastPointMeasuring(measuring.getPoint());
// Wenn der neue Wert der erste Eintrag in der Messstation
// ist braucht nichts weiteres kontrolliert werden
// => Wert wird hinzugefuegt
if(lastPointMeasuring == null){
this.measurings.add(measuring);
addcounter++;
if(backupCheck()){
app.save(backupSaveName);
}
return null;
}
//ueberpruefe ob der neue Wert nach der letzten Messung
//gemessen worden ist
if(!measuring.getTime().after(lastPointMeasuring.getTime())){
throw new ApplicationException("This time is earlier or equal than the last time");
}
//Wenn alle ueberpruefungen erfolgreich waren
//fuege den neuen Wert hinzu
this.measurings.add(measuring);
if(backupCheck()){
app.save(backupSaveName);
}
//Ermittle ob Warnungen ausgegeben werden
//Da alle Warnungen abhaengig davon sind ob Border im
//Unitsystem gesetzt ist wird zuerst ueberprueft
//ob Border gesetzt ist
if(measuring.getPoint().getUnitSystem().getBorder() != null){
if(MeasureValueTwiceOverBorder(measuring)){
retArg += "Value is twice Over Border\n";
}
if(isTwoMeasureValuesOverBorder(measuring,lastPointMeasuring)){
retArg += "Last two Values over Border\n";
}
if(isHalfOverBorder(measuring)){
retArg += "Average of the Values in the last hour over Border";
}
if(retArg != ""){
throw new ApplicationException(retArg);
}
}
//uebermittle diese Warnungen
if(retArg.equals("")){
return null;
}
else return retArg.substring(1);
}
/**
* Enfernt einen Eintrag aus der measurings Arraylist.
* Um loeschen zu koennen wird das Passwort der Messstation mitgeliefert und verglichen
* @param i index des messeintrags der entfernt werden soll
* @param pwd passwort der jeweiligen messstation
* @return null wenn entfernt werden konnte sonst "wrong password"
*/
public String remove(int i, String pwd)throws ApplicationException {
// 0 <= i < Anzahl der Eintrage in Measurings
if(this.measurings.get(i).getPoint().equalsPassword(pwd)){
this.measurings.remove(i);
return null;
}else throw new ApplicationException("Wrong Password");
}
/**
* Zaehlt die Eintraege in der measurings Arraylist
* @return Groesse der MeasuringsArraylist
*/
public Integer countMeasurings(){
return this.measurings.size();
}
/**
* Liefert das letzte Measuringobjekt,dass an der Messstation p erfasst wurde
* @param p Messstation p
* @return Measuringobjekt,dass zuletzt an Messation p erfasst wurde,
* null wenn noch kein Wert erfasst wurde
*/
private Measuring getlastPointMeasuring(Point p){
for(int i=countMeasurings()-1;i>=0;i--){
if(measurings.get(i).getPoint().getId()==p.getId()){
return measurings.get(i);
}
}
return null;
}
/**
* Prueft ob der letzte Messwert mehr als doppelt so gro� ist wie der Grenzwert
* Es wird vorrausgesetzt dass das Unitsystem Border und Borderref gesetzt hat
* @param m Messwert der ueberprueft wird
* @return true wenn ja, false wenn nein
* @throws ApplicationException
*/
private boolean MeasureValueTwiceOverBorder(Measuring m)throws ApplicationException{
UnitSystem us = m.getPoint().getUnitSystem();
double Border = us.transform(us.getBorder(), us.getBaseUnit()).getValue();
double refBorder = us.transform(us.getRefBorder(), us.getBaseUnit()).getValue();
double doubleBorder = Border + (Border - refBorder);
if(us.transform(m.getValue(), us.getBaseUnit()).getValue() > doubleBorder){
return true;
}
else return false;
}
/**
* Prueft ob die letzten beiden Messwerte, die in der Messstation des letzten Wertes gemessen wurden
* ueber dem Grenzwert liegen
* @return true wenn die letzten beiden messwerte ueber dem grenzwert waren, ansonsten false
*/
private boolean isTwoMeasureValuesOverBorder(Measuring measuring, Measuring lastPointMeasuring)throws ApplicationException{
UnitSystem us = measuring.getPoint().getUnitSystem();
if(countMeasurings() >= 2){
Value measuringValue = us.transform(measuring.getValue(),us.getBaseUnit());
Value lastPointMeasuringValue = us.transform(lastPointMeasuring.getValue(), us.getBaseUnit());
Value borderValue = us.transform(us.getBorder(), us.getBaseUnit());
if(measuringValue.getValue() > borderValue.getValue() &&
lastPointMeasuringValue.getValue() > borderValue.getValue()){
return true;
}
}
return false;
}
/**
* Liefert die aktuelle id des measuringseintrages
* @return die aktuelle id in der messwertliste. also im normalfall die letzte und somit die groesse der arraylist -1
*/
public Integer getId(){
return this.measurings.size()-1;
}
/**
* Prueft ob Messwerte valide sind
* @param m measutingobjekt
* @return null wenn messwert korrekt, ansonsten eine der Fehlermeldungen
* @throws ApplicationException
*/
private String isValid(Measuring m) throws ApplicationException {
String retArg = "";
//1. ueberpruefung auf MIN, MAX Werte bei value
UnitSystem us = m.getPoint().getUnitSystem();
if(us.getMin()!= null){
Value min;
if(us.getMin().getUnit().getName() != us.getBaseUnit().getName()){
min = us.getMin().getUnit().transFromUnitToBaseunit(us.getMin());
}else {
min = us.getMin();
}
Value value = m.getValue().getUnit().transFromUnitToBaseunit(m.getValue());
if(value.getValue() < min.getValue()){
return retArg+="Value is not plausible";
}
}
if(us.getMax()!= null){
Value max;
if(us.getMax().getUnit().getName() != us.getBaseUnit().getName()){
max = us.getMax().getUnit().transFromUnitToBaseunit(us.getMax());
}else {
max = us.getMax();
}
Value value = m.getValue().getUnit().transFromUnitToBaseunit(m.getValue());
if(value.getValue() > max.getValue()){
return retArg+="Value is not plausible";
}
}
//2. ueberpruefung auf MIN, Max Werte bei Datum
if( m.getTime().after(m.getPoint().getMAXTIME()) ||
m.getTime().before(m.getPoint().getMINTIME()) )
{
return retArg+="Time is not plausible";
}
//3. Pruefen ob die ID dieser Messung korrekt, also um 1 groesser als die letzte
//an derselben Messstation gemessene MessID ist
if(getlastPointMeasuring(m.getPoint()) != null){
Measuring lastPointMeasuring = getlastPointMeasuring(m.getPoint());
if(m.getID() <= lastPointMeasuring.getID()) {
return retArg+="MeasuringID is not plausible";
}
}
//4. Pruefen ob Value mehr als doppelt so gross wie der Grenzwert ist
if (retArg.equals("")) {
return null;
}
else {
return retArg.substring(1);
}
}
/**
* Prueft ob mehr als die Haelfte der in der letzten Stunde gemessenen Werte ueber dem Grenzwert liegen.
* Allerdings nur wenn in der letzten Stunde mindestens 5 Messwerte erfasst wurden.
* @return true wenn in der letzten stunde mindestens 5 messwerte erfasst wurden und mehr als die haelfte von diesen ueber dem grenzwert liegen
*/
private boolean isHalfOverBorder(Measuring measuring)throws ApplicationException{
int counter = 0;
int bcounter = 0;
UnitSystem us = measuring.getPoint().getUnitSystem();
GregorianCalendar lowerBorder = (GregorianCalendar)this.measurings.get(this.measurings.size()-1).getTime().clone();
lowerBorder.roll(GregorianCalendar.HOUR,-1);
if (this.measurings.size() > 0) {
for (int i = this.measurings.size()-1; i >= 0; i--) {
if ((lowerBorder.before(this.measurings.get(i).getTime()) ||
lowerBorder.equals(this.measurings.get(i).getTime()))&&
(this.measurings.get(i).getPoint().getId() == measuring.getPoint().getId())) {
counter++;
if(us.transform(this.measurings.get(i).getValue(), us.getBaseUnit()).getValue() >
us.transform(us.getBorder(),us.getBaseUnit()).getValue()){
bcounter++;
}
}else {
break;
}
}
}else {
return false;
}
if (bcounter != 0) {
if ((double)bcounter/(double)counter > 0.5 && counter >= 5) {
return true;
}else {
return false;
}
}else {
return false;
}
}
/**
* liefert den Wert an einer bestimmten Stelle der Arraylist
* @param i Stelle i der measutings Arraylist
* @return Wert an der Stelle i der measurings Arraylist
*/
public Measuring getMeasuring(int i) {
// 0 <= i < Eintraege in measurings Arraylist
return this.measurings.get(i);
}
/**
* Setzt Backupintervall auf einen bestimmten Wert i fest
* @param i Wert des Backupintervalls
*/
public void setBackupIntervall(int i){
this.backupIntervall = i;
}
/**
* Prueft ob ein Backup erstellt werden soll oder nicht
* @return true wenn ja, false wenn nein.
*/
private boolean backupCheck(){
if(backupIntervall > 0){
if(addcounter % backupIntervall == 0){
backupCounter++;
this.backupSaveName = "Backup " + backupCounter;
return true;
}else return false;
}else return false;
}
}